#include "Serialize.h"
#include "Buffer.h"
#include "StringList.h"
#include <vector>
#include "EArray.h"


namespace SerializeNS{
	
	//kontejner za mape serializable klasa
	EArray<CClassMapBase*> _ClassMaps;
	
	//indexer, cuva indexe klas mapa prema tipu, radi brzeg pristupa
	size_t _ClassMapsIndexTable[sizeof(EType)];

	
	void  Base::start(const char* SaveFileName, SerializeState State){
		CSerializer* Serializer = 0;
		if (State == state_deserialize){
			//Buffer = new BufferDeserialize("save");
		}
		else
		if (State == state_serialize){
			Serializer = new Serialize(SaveFileName);
			for (size_t i = 0; i < _ClassMaps.count(); i++){
				CClassMapBase* ClassInfoBase = _ClassMaps[i];
				for (size_t ii = 0; ii < ClassInfoBase->_IdVars.count(); ii++){
					VarInfo& Var = *ClassInfoBase->_Vars[ii];
					Var._NameIndex = (unsigned short)Serializer->_Strings->getIndexByString(Var._Name.c_str());
				}
			}
		}
		assert(Serializer);
		serialize(Serializer);
	}

	bool Base::serialize(CSerializer* Serializer)
	{
		assert(Serializer);
		CClassMapBase* ClassMap = _ClassMaps[_ClassMapsIndexTable[_Type]];
		//TODO -  ispraviti da podaci se ne serijalizuju naopako, treba (base...deliver) umesto (deliver..base)
		if (ClassMap->doSerialize(this, Serializer)) do {
			for (int i = 0; i < ClassMap->_Vars.count(); i++){
				ClassMap->_Vars[i]->serialize(this, ClassMap->_Buffer);
			}
			ClassMap = ClassMap->_Base;
		} while (ClassMap);
		return true;
	}

	bool Base::setClassType(CClassMapBase* ClassMap, EType Type)
	{
		ClassMap->_Type = Type;
		_Type = Type;
		_ClassMapsIndexTable[Type] = _ClassMaps.count();
		_ClassMaps.add(ClassMap);
		
		return true;
	}

	bool Base::setClassBase(CClassMapBase* ClassInfo, CClassMapBase* BaseClassInfo)
	{
		ClassInfo->_Base = BaseClassInfo;
		return true;
	}


	bool VarInfo::serialize(void* StartAddress, EDataBuffer* Buffer)
	{
		
		Buffer->push(getVarAddress(StartAddress, _Offset), _Size);
		return true;
	}


	bool VarInfoClass::serialize(void* StartAddress, EDataBuffer* Buffer)
	{
		return true;
	}


	bool VarInfoClassPointer::serialize(void* StartAddress, EDataBuffer* Buffer)
	{
		return true;
	}


	bool VarInfoString::serialize(void* StartAddress, EDataBuffer* Buffer)
	{
		return true;
	}


	CSerializer::CSerializer(const char* SaveName)
	{
		assert(s_Archive);
		_Stream = s_Archive->open(SaveName, true);
		assert(_Stream);
		_Strings = new CStringList;

		_DataBuffers = new EDataBuffer[_ClassMaps.count()];
	}

	CFileArchive* CSerializer::s_Archive = CFileArchive::openArchive("SaveTest.sav", true);


	Serialize::Serialize(const char* SaveName) : CSerializer(SaveName)
	{

	}

	Deserialize::Deserialize(const char* SaveName) : CSerializer(SaveName)
	{

	}
}
